package future;

import org.junit.Test;

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Random;
import java.util.concurrent.*;

/**
 * @author lilingzhi
 * @since 2022/12/30 11:19
 */
public class FutureDemo {

    @Test
    public void test(){
        LocalDateTime startTime = LocalDateTime.now();
        ExecutorService executorService = Executors.newCachedThreadPool();

        Future<Double> future = executorService.submit(new Callable<Double>() {
            /**
             * Computes a result, or throws an exception if unable to do so.
             *
             * @return computed result
             * @throws Exception if unable to compute a result
             */
            @Override
            public Double call() throws Exception {
                return doSomeThing();
            }
        });

        doSomeThingElse();
        try {
            Double result = future.get(1, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            // 打断异常
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
            // 计算出现异常
        } catch (TimeoutException e) {
            // 是否已经过期，异常
            e.printStackTrace();
        }
        LocalDateTime end = LocalDateTime.now();
        Duration between = Duration.between(startTime, end);
        long l = between.toMillis() / 1_000L;
        System.out.println(l);
    }


    /**
     * 如果没有异常处理 · 则该线程永远会阻塞
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Test
    public void test2() throws ExecutionException, InterruptedException {
        Future<Double> product = getPriceAsync("product");
        Double aDouble = product.get();
        System.out.println(aDouble);
    }

    /**
     * 如果异常则会抛出
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Test
    public void test3() throws ExecutionException, InterruptedException {
        CompletableFuture<Double> product = getPriceAsync2("product");
        Double aDouble = product.get();
        System.out.println(aDouble);
//        System.out.println(aDouble);
//        Double now = product.getNow(30D);
//        System.out.println(now);

//        Thread.sleep(30_000L);
    }


    @Test
    public void test4() throws ExecutionException, InterruptedException {
        CompletableFuture<Void> sdsd = CompletableFuture.runAsync( () -> calculatePrice("ds"));
//        Void unused = sdsd.get();
//        System.out.println(unused);
    }



    public CompletableFuture<Double> getPriceAsync2(String product){
        return CompletableFuture.supplyAsync(() -> calculatePrice(product));
    }

    public Future<Double> getPriceAsync(String product){
        CompletableFuture<Double> future = new CompletableFuture<>();
        new Thread( () ->{
            double v = calculatePrice(product);
            future.complete(v);
        }).start();
        return  future;
    }


    public static void delay(){
        try {
            Thread.sleep(1_000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public double getPrice(String product){
        return calculatePrice(product);
    }

    private double calculatePrice(String product) {
        delay();
        int i = 10 /0 ;
        double v = new Random().nextDouble() * product.charAt(0) + product.charAt(1);
        System.out.println("dsds"+v);
        return v;
    }

    private void doSomeThingElse() {
        try {
            Thread.sleep(10_000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private Double doSomeThing() {
        try {
            Thread.sleep(10_000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }
}
